package cc.core.pullrefresh;

import android.content.Context;
import android.os.Build;
import android.os.Parcelable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ExpandableListView;
import android.widget.FrameLayout;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.ListAdapter;
import android.widget.ListView;

import com.nineoldandroids.animation.Animator;
import com.nineoldandroids.animation.ObjectAnimator;
import com.nineoldandroids.animation.ValueAnimator;
import com.nineoldandroids.animation.ValueAnimator.AnimatorUpdateListener;

import cc.core.pullrefresh.extra.BaseFooterLayout;

/**
 * ClassName:PullRefreshBase <br/>
 * Date: 2015年6月22日 下午3:04:43 <br/>
 * PullRefreshListView</a>
 *
 * @author YuanChao
 */
public abstract class PullRefreshAbsListViewBase<T extends AbsListView> extends PullRefreshBase<T> implements IPullBase<T>, OnScrollListener {

    /**
     * 内部的ListView
     */
    protected T listview;
    protected ImageView headerImg;

    protected int firstVisibleItem;
    protected int lastVisiablePosition;
    protected int totalCount;
    private int scrollState;// 当前滑动的状态
    protected OnItemClickListener itemClickListener;
    protected OnScrollListener scrollListener;
    protected OnClickListener emptyViewClickListener;
    protected int topPadding;

    protected int mMotionPosition = 0;
    protected View motionView = this;

    protected ListAdapter mAdapter;

    // 当数据无法填充屏幕时无需加载更多
    private boolean canLoadMore = true;
    private boolean canCallRefresh;

    public T getListview() {
        return listview;
    }

    @Override
    public void setOnRefreshListener(OnRefreshListener listener) {
        this.refreshListener = listener;
    }

    public OnRefreshListener getOnRefreshListener() {
        return refreshListener;
    }


    public PullRefreshAbsListViewBase(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public PullRefreshAbsListViewBase(Context context) {
        super(context);
    }

    /**
     * <h1>View 的初始化</h1>
     * <p>
     * 实例化一个LineLayout对象{@link #layoutBase}，把{@link #headerView}和
     * {@link #listview} 添加到{@code #layoutBase}
     * </p>
     * F
     *
     * @param context
     */
    @Override
    protected void initView(Context context, AttributeSet attr) {
        super.initView(context, attr);
        listview = refreshView;
        listview.setOnScrollListener(this);
    }


    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        {
            if (ev.getAction() == MotionEvent.ACTION_UP)
                disallowIntercept = false;
            if (disallowIntercept) {
                return super.dispatchTouchEvent(ev);
            }
            mMotionPosition = 0;
            motionView = this;
            if (mode == Mode.DISABLE || mode == Mode.PULL_FROM_BOTTOM)
                return super.dispatchTouchEvent(ev);
            try {
                switch (ev.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        mMotionPosition = listview.pointToPosition((int) ev.getX(), (int) ev.getY());
                        motionView = getChildAt(mMotionPosition - firstVisibleItem);
                        mLastMotionY = mInitialMotionY = ev.getY();
                        break;
                    case MotionEvent.ACTION_MOVE:
                        // doMove(ev);
                        setPressed(false);
                        motionView.setPressed(false);
                        mLastMotionY = ev.getY();
                        doMove(ev);
                        break;
                    case MotionEvent.ACTION_UP:
                        if (isPulling) {
                            if (refreshListener == null) startHeadAnim(0f);
                            else {
                                if (state == State.HEAD_RELEASEING) {
                                    if (state != State.FOOTER_REFRESHING && state != State.HEAD_REFRESHING) {// 已经处于刷新的状态不需要回调
                                        state = State.HEAD_REFRESHING;
                                        refreshAnimStarted = true;
                                        startHeadAnim(getPullLimitDistance());
                                        updateState();
                                        canCallRefresh = true;
                                    }
                                } else {
                                    startHeadAnim(0f);
                                }
                            }
                            MotionEvent motionEvent = MotionEvent.obtain(1, 2, MotionEvent.ACTION_CANCEL, -1f, -1f, 0);
                            super.dispatchTouchEvent(motionEvent);
                            isPulling = false;
                        }
                        break;
                }
                // cancelSelectedState(ev);
                if (isPulling || headerScrolling) {
                    cancelChildViewPressState();
                    return true;
                } else
                    return super.dispatchTouchEvent(ev);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return super.dispatchTouchEvent(ev);
    }

    private void cancelChildViewPressState() {
        for (int i = 0; i < getChildCount(); i++) {
            View child = listview.getChildAt(i);
            child.setPressed(false);
            child.setSelected(false);
        }
    }

    boolean disallowIntercept;

    @Override
    public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
        this.disallowIntercept = disallowIntercept;
        super.requestDisallowInterceptTouchEvent(disallowIntercept);
    }

    public void setFooterRefreshError(boolean isError) {
        if (footerView != null) {
            state = State.FOOTER_REFRESHING;
            footerView.setError(isError);
        }
    }

    @Override
    protected void onRestoreInstanceState(Parcelable state) {
        try {
            super.onRestoreInstanceState(state);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onScrollStateChanged(AbsListView absListView, int i) {
        if (scrollListener != null) scrollListener.onScrollStateChanged(absListView, i);
        this.scrollState = i;
        // 判断是否滑动了最底部
        if (lastVisiablePosition >= totalCount - 1 && scrollState == SCROLL_STATE_IDLE && canLoadMore) {
            // 说明滚动到了最下面一个Item
            if (mode == Mode.BOTH || mode == Mode.PULL_FROM_BOTTOM) if (refreshListener != null) {
                if (mode == Mode.DISABLE || mode == Mode.PULL_FROM_TOP) return;
                if (state != State.FOOTER_REFRESHING && state != State.HEAD_REFRESHING) {// 已经处于刷新状态或者加载更多状态不需要再回调
                    state = State.FOOTER_REFRESHING;
                    footerView.setVisibility(View.VISIBLE);
                    refreshListener.onFooterRefresh();
                    refreshListener.onFooterRefresh(footerView);
                }
            }
        }
        if (onScrollListener != null) {
            onScrollListener.onScrollStateChanged(absListView, i);
        }
    }

    @Override
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
        if (scrollListener != null)
            onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount);
        this.firstVisibleItem = firstVisibleItem;

        // 当数据不能填充整个屏幕时，将隐藏FooterView
        if (totalItemCount <= visibleItemCount) {
            this.canLoadMore = false;
            if (footerView != null) footerView.setVisibility(GONE);
        } else {
            this.canLoadMore = true;
        }

        lastVisiablePosition = firstVisibleItem + visibleItemCount;
        totalCount = totalItemCount;
        if (onScrollListener != null) {
            onScrollListener.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount);
        }
    }

    protected void innerInit(Context context) {
        listview.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {

            @Override
            public void onGlobalLayout() {

                if (!shouldMeasureInitY) return;
                if (listview.getCount() > 0) {
                    mInitY = getLc(layoutBase.getChildAt(1))[1];
                    shouldMeasureInitY = !shouldMeasureInitY;
                }
            }
        });
        // 不显示顶部和底部拖拽时的阴影
        // if (Integer.parseInt(Build.VERSION.SDK) >= 9) {
        // this.setOverScrollMode(View.OVER_SCROLL_NEVER);
        // }
    }

    /**
     * 调用此方法前你应该先初始化{@link #footerView}
     *
     * @param listener
     */
    public void setFooterClickListener(OnClickListener listener) {
        footerView.setOnClickListener(listener);
    }

    /**
     * 返回 footerView
     *
     * @return
     */
    public BaseFooterLayout getFooterView() {
        return footerView;
    }

    /**
     * 隐藏FooterView
     */
    public void hideFooterView() {
        if (footerView != null) {
            if (listview instanceof ListView) {
                try {
                    if (((ListView) listview).getFooterViewsCount() == 1)
                        ((ListView) listview).removeFooterView(footerView);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 显示
     */
    public void showFooterView() {
        if (footerView != null) {
            footerView.setError(false);
            if (listview instanceof ListView) {
                if (((ListView) listview).getFooterViewsCount() == 0)
                    ((ListView) listview).addFooterView(footerView);
            }
        }
    }

    /**
     * 返回 headerView
     *
     * @return
     */
    public View getHeaderView() {
        return headerView;
    }

    /**
     * <p>
     * 设置下拉刷新的模式，你应该在{@link #setAdapter(ListAdapter)}之前调用这个方法
     * </p>
     *
     * @param mode
     */
    public void setMode(int mode) {
        super.setMode(mode);
        switch (mode) {
            case Mode.PULL_FROM_TOP:
                if (footerView != null) hideFooterView();
                break;
            case Mode.BOTH:
                if (footerView == null) initFooter(getContext(), attr);
                // footerView.setVisibility(View.VISIBLE);
                break;
            case Mode.PULL_FROM_BOTTOM:
                if (footerView == null) initFooter(getContext(), attr);
                // footerView.setVisibility(View.VISIBLE);
                break;
            case Mode.DISABLE:
                if (footerView != null) hideFooterView();
                break;
        }
    }

    public void onRefreshComplete() {
        this.state = State.NORMAL;
        startHeadAnim(0f);
        updateState();
    }

    @Override
    protected void updateFirstChildY() {
        if (shouldMeasureInitY && listview.getFirstVisiblePosition() == 0 && listview.getChildCount() > 0) {
            mInitFirstChildY = getLc(listview.getChildAt(0))[1];
            mInitY = getLc(layoutBase.getChildAt(1))[1];
        }
    }

    public void updateState() {
        switch (state) {
            case State.HEAD_REFRESHING:
                headerView.setRefreshing();
                break;
            case State.NORMAL:
            case State.HEAD_PULLING:
                headerView.setPullToRefresh();
                break;
            case State.HEAD_RELEASEING:
                headerView.setReleaseToRefresh();
                break;
        }
    }

    /**
     * 更新{@link #headerView}，并设置全局的状态
     */
    @Override
    protected void updateHead() {
        if (refreshAnimStarted) return;
        mHeaderY = getLc(listview.getChildAt(0))[1];
        if (-newScrollValue >= pullLimitDistance) {
            this.state = State.HEAD_RELEASEING;
            updateState();
        } else {
            this.state = State.HEAD_PULLING;
            updateState();
        }
    }

    /**
     * 计算位置，判断是否达到顶部
     */
    @Override
    public boolean readyPull(MotionEvent ev) {
        if (isPulling) {
            return true;
        }
        if (listview.getAdapter().getCount() != 0) //如果没有数据，不要重新计算child的高度。
        {
            mInitFirstChildY = getLc(listview.getChildAt(0))[1];
        }

        if (listview.getAdapter().getCount() == 0 || (-newScrollValue > 0 && firstVisibleItem == 0 &&
                mInitY == (mInitFirstChildY - topPadding))) {
            mInitialMotionY = ev.getY();
            newScrollValue = 1;
            isPulling = true;
            return true;
        } else {
            isPulling = false;
            return false;
        }
    }


    /**
     * 刷新结束后回弹动画
     *
     * @param value 最多可以设置两个值
     */
    public void startHeadAnim(float... value) {
        float startValue, endValue;
        ObjectAnimator anim = null;
        if (value.length == 1) {
            startValue = value[0];
            anim = ObjectAnimator.ofFloat(layoutBase, "translationY", startValue).setDuration(300);
        } else {
            startValue = value[0];
            endValue = value[1];
            anim = ObjectAnimator.ofFloat(layoutBase, "translationY", startValue, endValue).setDuration(300);
        }
        anim.addListener(new Animator.AnimatorListener() {
            boolean isRefreshAnim = false;// 是否需要执行下拉刷新时加载的动画

            public void onAnimationStart(Animator animator) {
                if (refreshAnimStarted) isRefreshAnim = true;
                refreshAnimStarted = false;
                headerScrolling = true;
                state = State.HEAD_RELEASEING;
            }

            public void onAnimationEnd(Animator animator) {
                if (isRefreshAnim) {
                    isRefreshAnim = false;
                    headerScrolling = true;
                    headerView.onHeaderRefreshing(true);
                    state = State.HEAD_REFRESHING;
                    updateState();
                } else {
                    headerView.onHeaderRefreshing(false);
                    state = State.NORMAL;
                }
                headerScrolling = false;
                updateState();
                shouldMeasureInitY = true;
                innerInit(getContext());
                updateFirstChildY();
                if (canCallRefresh) {
                    refreshListener.onHeaderRefresh();
                    refreshListener.onHeaderRefresh(headerView);
                    canCallRefresh = false;
                }
            }

            public void onAnimationCancel(Animator animator) {
            }

            public void onAnimationRepeat(Animator animator) {
            }
        });
        anim.addUpdateListener(new AnimatorUpdateListener() {

            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                Float value = (Float) animation.getAnimatedValue();
                if (pullListener != null && !refreshAnimStarted) {
                    pullListener.onPullDown(value);
                }
                headerView.setAnimValue(value);
                updateHead();
            }
        });
        anim.start();
    }

    @Override
    public void showHeaderRefresh() {
        refreshAnimStarted = true;
        canCallRefresh = false;
        startHeadAnim(headerHeight);
    }

    @Override
    public T getRefreshView() {
        return listview;
    }

    public void setOnItemClickListener(final OnItemClickListener listener) {
        listview.setOnItemClickListener(new OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                if (footerView != null && view == footerView) return;
                if (listener != null) {
                    if (listview instanceof ListView) {
                        if (position >= ((ListView) listview).getHeaderViewsCount() - 1)
                            listener.onItemClick(parent, view, position - ((ListView) listview).getHeaderViewsCount(), id);
                    }
                }
            }
        });
    }

    public OnScrollListener getScrollListener() {
        return scrollListener;
    }

    public void setScrollListener(OnScrollListener scrollListener) {
        this.scrollListener = scrollListener;
    }

    /**
     * 设置无数据时{@link #listview}的EmptyViewt</br>
     *
     * @param emptyView 它应该是一个FrameLayout</br>
     */
    @Override
    public void setEmptyView(View emptyView) {
        FrameLayout emptyLayout;
        if (listview.getEmptyView() == null) {
            emptyLayout = new FrameLayout(getContext());
            emptyLayout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
            emptyView.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
            emptyLayout.addView(emptyView);
            emptyView.setVisibility(View.VISIBLE);
            ((ViewGroup) listview.getParent()).addView(emptyLayout);
            listview.setEmptyView(emptyLayout);
        } else {
            emptyLayout = (FrameLayout) listview.getEmptyView();
            emptyLayout.removeAllViews();
            emptyLayout.setVisibility(View.VISIBLE);
            emptyLayout.addView(emptyView);
        }
        emptyLayout.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                if (emptyViewClickListener != null) emptyViewClickListener.onClick(v);
            }
        });

    }

    public OnClickListener getEmptyViewClickListener() {
        return emptyViewClickListener;
    }

    public void setEmptyViewClickListener(OnClickListener clickListener) {
        this.emptyViewClickListener = clickListener;
    }

    /**
     * 设置Adapter
     */
    public void setAdapter(ListAdapter adapter) {
        mAdapter = adapter;
        if (Build.VERSION.SDK_INT >= 11) {
            listview.setAdapter(adapter);
        } else {
            if (listview instanceof ListView) {
                ((ListView) listview).setAdapter(adapter);
            } else if (listview instanceof GridView) {
                ((GridView) listview).setAdapter(adapter);
            } else if (listview instanceof ExpandableListView) {
                ((ExpandableListView) listview).setAdapter(adapter);
            }
        }
        innerInit(getContext());
        updateFirstChildY();
    }

    public ListAdapter getAdapter() {
        return mAdapter;
    }
}
